package com.com.designpatterns.function;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.IllegalFormatConversionException;
import java.util.List;

/**
 * Created by User on 22/07/2015.
 */
public class Functions
{
    interface Function<A, B, X extends Throwable>
    {
       public B apply(A x) throws X;
    }

    public static <A, B, X extends Throwable> List<B> applyAll(Function<A, B, X> f, List<A> listA) throws X
    {
        List<B> listB = new ArrayList<>(listA.size());
        for(A a : listA)
        {
            listB.add(f.apply(a));
        }
        return listB;
    }

    public static void main(String[] args)
    {
        List<String> a = new ArrayList<>();
        a.add("java.lang.Thread");
        a.add("java.lang.Runnable");
        //a.add("C11");


        Function<String, Integer, Exception> length = new Function<String, Integer, Exception>()
        {
          @Override
          public Integer apply(String x) throws Exception {
            return x.length();
          }
        };

        Function<String, Class<?>, ClassNotFoundException> clazz = new Function<String, Class<?>, ClassNotFoundException>() {
            @Override
            public Class<?> apply(String x) throws ClassNotFoundException {
                return Class.forName(x);
            }
        };

        Function<String, Method, Exception> getRunMethod = new Function<String, Method, Exception>() {
            @Override
            public Method apply(String x) throws ClassNotFoundException, NoSuchMethodException {
                return Class.forName(x).getMethod("run");
            }
        };


        try
        {
            List<Integer> integers = Functions.applyAll(length, a);
            for(Integer i : integers)
            {
                System.out.println(i);
            }
        }
        catch (Exception ex)
        {
            System.out.println(ex.getCause());
        }

        try
        {
            List<Class<?>> classes = Functions.applyAll(clazz, a);
            for(Class<?> claxx : classes)
            {
                System.out.println(claxx.getName());
            }
        }
        catch (ClassNotFoundException ex)
        {
            System.out.println(ex.getStackTrace());
        }

        try
        {
            List<Method> methods = Functions.applyAll(getRunMethod, a);
            for(Method method : methods)
            {
                System.out.println(method.getName());
            }
        }
        catch (Exception ex)
        {
            System.out.println(ex.getStackTrace());
        }
    }


}
